/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BatteryListener.h"

#include "BasicServicesKit/oh_commonevent_support.h"
#include "CordovaViewController.h"
#include "BasicServicesKit/ohbattery_info.h"
#include "cJSON.h"

REGISTER_PLUGIN_CLASS(BatteryListener)
bool BatteryListener::execute(const string&  action, cJSON* args, CallbackContext cbc)
{
    if(action == "start") {
        m_cbc = cbc;
        if(!CreateSubscribeInfo()) {
            cbc.error("Error CreateSubscribeInfo");
        } else if(!CreateSubscriber()) {
            cbc.error("Error CreateSubscriber");
        } else if(!Subscribe()) {
            cbc.error("Error Subscribe");
        } else {
            int nSoc = OH_BatteryInfo_GetCapacity();
            BatteryInfo_BatteryPluggedType pluggedType = OH_BatteryInfo_GetPluggedType();
            cJSON* pRet = cJSON_CreateObject();
            cJSON_AddNumberToObject(pRet, "level", nSoc);
            if(pluggedType == PLUGGED_TYPE_NONE) 
                cJSON_AddFalseToObject(pRet, "isPlugged");
            else 
                cJSON_AddTrueToObject(pRet, "isPlugged");
            PluginResult pluginResult(PluginResult::OK, pRet);
            pluginResult.setKeepCallback(true);
            m_cbc.sendPluginResult(pluginResult);
        }
    } else if(action == "stop") {
        if(!UnSubscribe()) {
            cbc.error("Error UnSubscribe");
            return true;
        }
        DestroySubscriber();
        DestroySubscribeInfo();
        PluginResult pluginResult(PluginResult::NO_RESULT);
        pluginResult.setKeepCallback(false);
        m_cbc.sendPluginResult(pluginResult);
        cbc.success();
    }
    return true;
}

bool BatteryListener::CreateSubscribeInfo()
{
    const char* events[2];
    events[0] = COMMON_EVENT_BATTERY_CHANGED;
    events[1] = COMMON_EVENT_BATTERY_LOW;
    
    // 创建订阅者信息
    m_info = OH_CommonEvent_CreateSubscribeInfo(events, 2);
    if(m_info == nullptr) {
        return false;
    }
    
    //设置订阅者权限
    if(OH_CommonEvent_SetPublisherPermission(m_info, "") != COMMONEVENT_ERR_OK) {
        return false;
    }
    
    return true;
}

void BatteryListener::DestroySubscribeInfo()
{
    OH_CommonEvent_DestroySubscribeInfo(m_info);
    m_info = nullptr;
}

bool BatteryListener::CreateSubscriber()
{
    m_subscriber =  OH_CommonEvent_CreateSubscriber(m_info, BatteryListener::onRevice);
    if(m_subscriber == nullptr) {
        return false;
    }
    return true;
}

void BatteryListener::DestroySubscriber()
{
    OH_CommonEvent_DestroySubscriber(m_subscriber);
    m_subscriber = nullptr;
}

bool BatteryListener::Subscribe()
{
    if(OH_CommonEvent_Subscribe(m_subscriber) != COMMONEVENT_ERR_OK) {
        return false;
    }
    return true;
}

bool BatteryListener::UnSubscribe()
{
    if(OH_CommonEvent_UnSubscribe(m_subscriber) != COMMONEVENT_ERR_OK) {
        return false;
    }
    return true;
}

void BatteryListener::onRevice(const CommonEvent_RcvData *data)
{
    BatteryListener* pBatteryListener = (BatteryListener*)((CordovaViewController*)Application::g_cordovaViewController)->getPluginManager()->getPlugin("Battery");
    pBatteryListener->updateBatteryInfo(data);
}

void BatteryListener::updateBatteryInfo(const CommonEvent_RcvData *data)
{
    // 获取回调公共事件名称
    string strEvent = OH_CommonEvent_GetEventFromRcvData(data);
    if(strEvent != COMMON_EVENT_BATTERY_CHANGED && strEvent != COMMON_EVENT_BATTERY_LOW) {
        return;
    }
    
    // 获取回调公共事件附件信息
    const CommonEvent_Parameters *parameters = OH_CommonEvent_GetParametersFromRcvData(data);
    
    int nSoc = 0;
    BatteryInfo_BatteryPluggedType pluggedType;
    if (OH_CommonEvent_HasKeyInParameters(parameters, COMMON_EVENT_KEY_CAPACITY)) {
        nSoc = OH_CommonEvent_GetIntFromParameters(parameters, COMMON_EVENT_KEY_CAPACITY, 0);
    }
    
    if (OH_CommonEvent_HasKeyInParameters(parameters, COMMON_EVENT_KEY_PLUGGED_TYPE)) {
        pluggedType = (BatteryInfo_BatteryPluggedType)OH_CommonEvent_GetIntFromParameters(parameters, COMMON_EVENT_KEY_PLUGGED_TYPE, 0);
    }
    
    cJSON* pRet = cJSON_CreateObject();
    cJSON_AddNumberToObject(pRet, "level", nSoc);
    if(pluggedType == PLUGGED_TYPE_NONE) 
        cJSON_AddFalseToObject(pRet, "isPlugged");
    else 
        cJSON_AddTrueToObject(pRet, "isPlugged");
    PluginResult pluginResult(PluginResult::OK, pRet);
    pluginResult.setKeepCallback(true);
    m_cbc.sendPluginResult(pluginResult);
    cJSON_Delete(pRet);
}
